package main

import "fmt"

type Student struct {
	name    string
	age     int
	married bool
	sex     int8
}

func main() {

	num := 32
	numPointer := &num
	fmt.Println("得到结论,指针的值会某个对象的地址,指针本身也有一个内存地址,这2个地址是不一样的")
	fmt.Printf("numPointer %T , %v , *numPointer == %v , &numPointer == %v \n", numPointer, numPointer, *numPointer, &numPointer)

	fmt.Println("打印 *& 的值")
	fmt.Printf("*&num ==  %T , %v , *&numPointer ==  %T , %v \n", *&num, *&num, *&numPointer, *&numPointer)
	fmt.Println("打印  &numPointer 的值 , 得到 &numPointer 的类型变化为指向指针的指针")
	fmt.Printf(" &numPointer 分开打印  == %T ,%v", &numPointer, &numPointer)

	fmt.Println("打印 *& 和 &* , &* 这种语法只有指针类型能使用, &*  等价于 *& ,使用后都等于指针本身")
	fmt.Printf(" *&num %T , %v 和 &*numPointer %T , %v ", *&num, *&num, &*numPointer, &*numPointer)

	fmt.Println("打印 student ")
	s1 := Student{"steven", 35, true, 1}
	s2 := Student{"sunny", 20, false, 0}

	s1Pointer := &s1
	s2Pointer := &s2

	fmt.Printf("s1Pointer name == %v , age == %v  ", (*s1Pointer).name, (*s1Pointer).age)
	fmt.Printf("s2Pointer married == %v , sex == %v  \n", (*s2Pointer).married, (*s2Pointer).sex)

	//空指针
	if s1Pointer != nil {
		fmt.Println("s1Pointer 不为空")
	}

	num1 := 20
	num2 := &num1
	fmt.Println(" num1 == ", num1, " num2 == ", num2)
	*num2 = 50
	*num2++
	fmt.Println(" num2 == ", num2, "  *num2 == ", *num2)
	change(num2)
	fmt.Println(" num2 == ", num2, "  *num2 == ", *num2)
	//指针数组
	var pointerArray [3]*string
	fmt.Printf("pointerArray  %T , %v \n", pointerArray, pointerArray)
	citys := [3]string{"昆明", "成都", "威信"}
	for index := range citys {
		pointerArray[index] = &citys[index]
	}

	fmt.Printf(" 赋值后的 pointerArray  %T , %v \n", pointerArray, pointerArray)
	for index, elem := range pointerArray {
		fmt.Println("赋值后的 pointerArray 第 ", index, " 个元素,值是  ", *elem)
	}

	//指向指针的指针
	num = 10
	numPtr := &num
	numPptr := &numPtr
	fmt.Println("numPtr 的内存地址是 ", numPtr, " 值是 ", *numPtr)
	fmt.Printf("numPptr %T , %v , numPptr 的值是 %v  \n", numPptr, numPptr, **numPptr)
}

func change(val *int) {
	*val = 30
}
